home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcpp / cpp.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  10KB  |  543 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  CPP.C
  9.  *
  10.  */
  11.  
  12. #include "defs.h"
  13.  
  14. Prototype Include *PushBase;
  15. Prototype char WhiteSpace[256];
  16. Prototype char SpecialChar[256];
  17. Prototype char SymbolChar[256];
  18.  
  19. Prototype void InitCpp(void);
  20. Prototype long cpp(long, int, char *, FILE *, char *, long);
  21. Prototype long SkipCommentLine(ubyte *, long, long);
  22. Prototype long SkipComment(ubyte *, long, long);
  23. Prototype long ExtSymbol(ubyte *, long, long);
  24. Prototype long SkipString(char *, long, long);
  25. Prototype long SkipSingleSpec(char *, long, long);
  26. Prototype void Dump(char *, long, long);
  27. Prototype void DoLineSpec(void);
  28.  
  29. Include *PushBase;
  30. char WhiteSpace[256];
  31. char SpecialChar[256];
  32. char SymbolChar[256];
  33.  
  34. void
  35. InitCpp()
  36. {
  37.     short i;
  38.  
  39.     WhiteSpace[9] = 1;
  40.     WhiteSpace[' '] = 1;
  41.     WhiteSpace['\r'] = 1;
  42.     WhiteSpace['l'&31] = 1;
  43.  
  44.     for (i = '0'; i <= '9'; ++i)
  45.     SymbolChar[i] = 1;
  46.     for (i = 'a'; i <= 'z'; ++i)
  47.     SymbolChar[i] = 1;
  48.     for (i = 'A'; i <= 'Z'; ++i)
  49.     SymbolChar[i] = 1;
  50.     SymbolChar['_'] = 1;
  51.     SymbolChar[1] = 1;        /*    special for macro replace */
  52.  
  53.     SpecialChar['\''] = 1;
  54.     SpecialChar['\"'] = 1;
  55.     SpecialChar['/'] = 1;
  56.     SpecialChar['?'] = 1;
  57. }
  58.  
  59. long
  60. cpp(oldi, level, file, fi, xbuf, xbytes)
  61. long oldi;
  62. int level;
  63. char *file;
  64. FILE *fi;
  65. char *xbuf;
  66. long xbytes;
  67. {
  68.     long len;
  69.     long i;
  70.     long w;
  71.     short ifIndex = IfIndex;
  72.     ubyte *base;
  73.     Include inc;
  74.  
  75.     if (level >= MAX_INCLUDE_LEVEL)
  76.     cerror(EFATAL_MAX_INCLUDE, level);
  77.  
  78.     if (fi == NULL && xbuf == NULL) {
  79.     ErrorOpenFailed(file, 0);
  80.     return(oldi);
  81.     }
  82.     if (fi) {
  83.     if (StripOpt == 0)
  84.         fprintf(Fo, "# 1 \"%s\" %d\n", file, level);
  85.     fseek(fi, 0L, 2);
  86.     len = ftell(fi);
  87.     if (len < 0) {
  88.         cerror(EERROR_FILE_SIZE, file, len);
  89.         fclose(fi);
  90.         return(oldi);
  91.     }
  92.     base = malloc(len+1);
  93.     if (base == NULL)
  94.         ErrorNoMemory();
  95.     fseek(fi, 0L, 0);
  96.     { 
  97.         int n;
  98.  
  99.         if ((n = fread(base, 1, len, fi)) != len) {
  100.         cerror(EERROR_READ_ERROR, file);
  101.         fclose(fi);
  102.         return(oldi);
  103.         }
  104.     }
  105.     fclose(fi);     /*  fi no longer valid */
  106.  
  107.     base[len] = 0;     /*  emergency terminator to prevent bad code from crashing us!  */
  108.  
  109.     /*
  110.      *  Check for tri-graphs, modify accordingly
  111.      */
  112.  
  113.     if (TriGraph) {
  114. #ifdef NO_ASM
  115.         char *ptr = base;
  116.         char c;
  117.  
  118.         while ((c = *ptr) != 0) {
  119.         ++ptr;
  120.         if (c == '?' && *ptr == '?') {
  121.             if ((c = TriGraphConvert(ptr[1])) != 0) {
  122.             ptr[-1] = c;
  123.             len -= 2;
  124.             movmem(ptr + 2, ptr, len - (ptr - (char *)base));
  125.             }
  126.         }
  127.         }
  128. #else
  129.         len = HandleTriGraphs(base) - base;
  130. #endif
  131.     }
  132.     } else {         /*  else macro  */
  133.     base = xbuf;
  134.     len = xbytes;
  135.     }
  136.     dbprintf(("CPP %s (%ld)\n", file, len));
  137.  
  138.     if (PushBase)
  139.     PushBase->Index = oldi;
  140.  
  141.     inc.Next = PushBase;
  142.     inc.FileName = file;
  143.     inc.LineNo     = 1;
  144.     inc.Level     = level;
  145.     inc.IsFile     = (fi) ? 1 : 0;
  146.     inc.MaxIndex = len;
  147.     inc.Base     = base;
  148.     PushBase = &inc;
  149.  
  150.     {
  151.     short nl = 1;                /*    newline just occured */
  152.     short c;
  153.     short stringtize = 0;
  154.  
  155.     for (i = w = 0; i < len; ) {
  156.         c = base[i];
  157.  
  158.         /*
  159.          *  White space.  If stripping, strip out completely except when
  160.          *  not preceeded by a newline (leave one whitespace char), if
  161.          *  not stripping then copy whitespace.
  162.          */
  163.  
  164.         if (WhiteSpace[c]) {
  165.         if (StripOpt) {
  166.             ++i;
  167.             if (nl == 0)
  168.                 Dump(base, w, i);
  169.             while (i < len && WhiteSpace[base[i]])
  170.             ++i;
  171.             w = i;
  172.         } else {
  173.             ++i;
  174.         }
  175.         continue;
  176.         }
  177.         if (c == '\n') {                /*  newline              */
  178.         /*
  179.          *  If stripping, skip newlines after the first.
  180.          */
  181.  
  182.         if (StripOpt) {
  183.             ++i;
  184.             if (nl == 0) {
  185.             Dump(base, w, i);
  186.             if (w == i-1 || base[i-2] != '\\')
  187.                 nl = 1;
  188.             }
  189.             w = i;
  190.             continue;
  191.         }
  192.  
  193.         /*
  194.          *  If line continuation force resynchronization and set nl
  195.          *  to 0.  Else if line spec forced then dump to just before
  196.          *  the newline, execute a line spec.
  197.          */
  198.  
  199.         if (w < i && base[i-1] == '\\') {
  200.             ForceLineSpec = 1;
  201.             Dump(base, w, i - 1);
  202.             w = i + 1;
  203.             nl = 0;
  204.         } else if (ForceLineSpec) {
  205.             Dump(base, w, i);
  206.             w = i;
  207.             DoLineSpec();
  208.             nl = 1;
  209.         } else {
  210.             nl = 1;
  211.         }
  212.         ++i;
  213.         ++inc.LineNo;
  214.         continue;
  215.         }
  216.  
  217.         /*
  218.          *  Handle directive or token pasting
  219.          */
  220.  
  221.         if (c == '#' && !StripOpt) {
  222.         if (nl && fi) {
  223.             dbprintf(("directive\n"));
  224.             Dump(base, w, i);
  225.                         /*    execute directive    */
  226.             w = i = HandleDirective(base, i + 1, len);
  227.         } else if (base[i+1] == '#') {
  228.             long si = i + 2;
  229.             while (i >= w && WhiteSpace[base[--i]]);
  230.             ++i;
  231.             Dump(base, w, i);
  232.             i = si;
  233.             while (i < len && WhiteSpace[base[i]])
  234.             ++i;
  235.             w = i;
  236.         } else if (fi == NULL) {
  237.             Dump(base, w, i);
  238.             stringtize = 1;
  239.             w = ++i;
  240.         } else {
  241.             ++i;
  242.         }
  243.         continue;
  244.         }
  245.  
  246.         /*
  247.          *    Do not misinterpret a number as a symbol, especially parts
  248.          *    of the number that contain characters such as 0x23 or
  249.          *    0.234E+4  It will suffice to include '.' in our definition
  250.          *    of a symbol for this loop
  251.          *
  252.          *    Note that embedded characters in numbers will not be handled
  253.          *    by DC1 if symbolized for precompiled includes, but the
  254.          *    processing of this is handled in PRECOMP.C, not here.
  255.          */
  256.  
  257.         if (c >= '0' && c <= '9') {
  258.             nl = 0;        /*    NOT a directive      */
  259.         for (++i; i < len && (SymbolChar[c = base[i]] || c=='.'); ++i)
  260.             ;
  261.         continue;
  262.         }
  263.  
  264.         /*
  265.          *    symbol?
  266.          */
  267.  
  268.         if (IfEnabled && SymbolChar[c]) {
  269.         long b = i;
  270.         Sym *node;
  271.  
  272.             nl = 0;        /*    NOT a directive      */
  273.         i = ExtSymbol(base, i, len);    /*  extract symbol     */
  274.         if ((node = FindSymbol(base + b, i - b)) != NULL) {
  275.             if (node->Type && SF_MACROARG && stringtize)
  276.             node->Type |= SF_STRINGIZE;
  277.             Dump(base, w, b);
  278.             w = i = HandleSymbol(node, base, i, len);
  279.             node->Type &= ~SF_STRINGIZE;
  280.         } else if (PreCompFlag) {
  281.             short t;
  282.  
  283.             /*
  284.              *    Precomp optimization
  285.              */
  286.  
  287.             if ((t = PreCompSymbol(base + b, i - b)) != 0) {
  288.             Dump(base, w, b);
  289.             w = i;
  290.             putc(((char *)&t)[0], Fo);
  291.             putc(((char *)&t)[1], Fo);
  292.             }
  293.         }
  294.         stringtize = 0;
  295.         continue;
  296.         }                    /*    delete comments      */
  297.         if (stringtize)
  298.         cerror(EERROR_STRINGTIZE);
  299.  
  300.         /*
  301.          * Strip out embedded comments.  Leave nl flag intact if -strip
  302.          * option was specified allowing us to strip whole sections,
  303.          * including newlines.
  304.          */
  305.  
  306.         if (SpecialChar[c]) {
  307.         if (c == '/') {
  308.             if (base[i+1] == '*') {
  309.             if (StripOpt == 0 || nl == 0)
  310.                 Dump(base, w, i);
  311.             w = i = SkipComment(base, i + 2, len);
  312.             if (nl == 0 || StripOpt == 0)
  313.                 putc(' ', Fo);
  314.             continue;
  315.             }
  316.             if (base[i+1] == '/' && SlashSlashOpt) {
  317.             if (StripOpt == 0 || nl == 0)
  318.                 Dump(base, w, i);
  319.             w = i = SkipCommentLine(base, i + 2, len);
  320.             continue;
  321.             }
  322.         }
  323.         nl = 0;
  324.         if (c == '\'') {
  325.             i = SkipSingleSpec(base, i + 1, len);
  326.             continue;
  327.         }
  328.         if (c == '\"') {
  329.             i = SkipString(base, i + 1, len);
  330.             continue;
  331.         }
  332.         }
  333.         nl = 0;
  334.         ++i;
  335.     }
  336.     Dump(base, w, i);
  337.     /* w = i */
  338.     }
  339.  
  340.     if (xbuf == NULL)
  341.     free(base);
  342.  
  343.     if (IfIndex != ifIndex)
  344.     cerror(EWARN_IFS_LEFT_PENDING, IfIndex, ifIndex);
  345.  
  346.     PushBase = inc.Next;
  347.  
  348.     if (PushBase) {
  349.     if (fi)
  350.         DoLineSpec();
  351.     return(PushBase->Index);
  352.     }
  353.     return(0);
  354. }
  355.  
  356. long
  357. SkipCommentLine(base, i, max)
  358. ubyte *base;
  359. long i;
  360. long max;
  361. {
  362.     while (i < max && base[i] != '\n')
  363.     ++i;
  364.     if (i == max)
  365.     cerror(EERROR_UNEXPECTED_EOF);
  366.     return(i);
  367. }
  368.  
  369. long
  370. SkipComment(base, i, max)
  371. ubyte *base;
  372. long i;
  373. long max;
  374. {
  375.     char c;
  376.  
  377.     while (i < max) {
  378.     c = base[i];
  379.     if (c == '/' && base[i+1] == '*')
  380.         cerror(EWARN_NESTED_COMMENT);
  381.     if (c == '*' && base[i+1] == '/')
  382.         break;
  383.     if (c == '\n') {
  384.         ++PushBase->LineNo;
  385.         if (StripOpt == 0)
  386.             putc('\n', Fo);
  387.     }
  388.     ++i;
  389.     }
  390.     if (i == max) {
  391.     cerror(EERROR_UNEXPECTED_EOF);
  392.     } else {
  393.     i += 2;
  394.     if (i > max)
  395.         cerror(EFATAL_SOFTERROR_177);
  396.     }
  397.     return(i);
  398. }
  399.  
  400. long
  401. ExtSymbol(base, i, max)
  402. ubyte *base;
  403. long i;
  404. long max;
  405. {
  406. #ifdef DEBUG
  407.     long b = i;
  408. #endif
  409.     char *sc = SymbolChar;
  410.  
  411.     while (i < max && sc[base[i]])
  412.     ++i;
  413.  
  414.     dbprintf(("ExtSymbol: %.*s\n", (int)(i - b), base + b));
  415.  
  416.     return(i);
  417. }
  418.  
  419. #ifdef NOTDEF
  420.  
  421. /*
  422.  *  This routine strips comments from a buffer
  423.  */
  424.  
  425. void
  426. StripComments(buf, bytes)
  427. char *buf;
  428. long bytes;
  429. {
  430.     char c;
  431.     long i;
  432.     long b;
  433.  
  434.     for (i = 0; i < bytes; ++i) {
  435.     if (buf[i] == '/' && i + 1 < bytes) {
  436.         if (buf[i+1] == '*') {
  437.         b = i;
  438.         i += 2;
  439.         while (i < bytes) {
  440.             if (buf[i] == '*' && buf[i+1] == '/' && i + 1 < bytes) {
  441.             i += 2;
  442.             break;
  443.             }
  444.             ++i;
  445.         }
  446.         setmem(buf + b, i - b, ' ');
  447.         } else if (buf[i+1] == '/' && SlashSlashOpt) {
  448.         b = i;
  449.         while (i < bytes && buf[i] != '\n')
  450.             ++i;
  451.         setmem(buf + b, i - b, ' ');
  452.         --i;
  453.         }
  454.     }
  455.     }
  456. }
  457.  
  458. #endif
  459.  
  460. long
  461. SkipString(char *base, long i, long max)
  462. {
  463.     while (i < max && base[i] != '\"') {
  464.     /*
  465.      *  Embedded newline with no previous backslash
  466.      */
  467.  
  468.     if (base[i] == '\n') {
  469.         cerror(EERROR_UNTERMINATED_STRING);
  470.         break;
  471.     }
  472.  
  473.     /*
  474.      *  Leave backslashes alone.  The specical case of a \ followed
  475.      *  by a newline is handled by DC1
  476.      */
  477.  
  478.     if (base[i] == '\\') {
  479.         ++i;
  480.     }
  481.     ++i;
  482.     }
  483.     if (i < max)
  484.     ++i;
  485.     return(i);
  486. }
  487.  
  488. long
  489. SkipSingleSpec(char *base, long i, long max)
  490. {
  491.     while (i < max && base[i] != '\'') {
  492.     if (base[i] == '\n') {
  493.         cerror(EERROR_UNTERMINATED_CHARCONST);
  494.         break;
  495.     }
  496.     if (base[i] == '\\')
  497.         ++i;
  498.     ++i;
  499.     }
  500.     if (i < max)
  501.     ++i;
  502.     return(i);
  503. }
  504.  
  505. void
  506. Dump(base, w, i)
  507. char *base;
  508. long w;
  509. long i;
  510. {
  511.     if (w < i) {
  512.     if (IfEnabled) {
  513.         if (GlobalStringize) {
  514.         long n;
  515.         for (n = w; n < i; ++n) {
  516.             char c = base[n];
  517.             if (c < 32 || c == '\"' || c == '\'' /* || c == '\\'*/) {
  518.             fprintf(Fo, "\\%03o", (ubyte)c);
  519.             } else {
  520.             putc(c, Fo);
  521.             }
  522.         }
  523.         } else {
  524.         fwrite(base + w, 1, i - w, Fo);
  525.         }
  526.     } else {
  527.         while (w < i) {
  528.         if (base[w] == '\n')
  529.             fputc('\n', Fo);
  530.         ++w;
  531.         }
  532.     }
  533.     }
  534. }
  535.  
  536. void
  537. DoLineSpec()
  538. {
  539.     fprintf(Fo, "\n# %ld \"%s\" %ld\n", PushBase->LineNo, PushBase->FileName, PushBase->Level);
  540.     ForceLineSpec = 0;
  541. }
  542.  
  543.